● Zion Boggan
repos/Stepping App/apps/web/src/app/city/[slug]/profile/[kind]/[id]/page.tsx
zionboggan.com ↗
121 lines · tsx
History for this file →
1
import Link from "next/link";
2
import { notFound } from "next/navigation";
3
import { serverCaller } from "@/lib/trpc/server";
4
 
5
export const dynamic = "force-dynamic";
6
 
7
const KIND_LABEL: Record<string, string> = {
8
  dj: "DJ",
9
  promoter: "Promoter",
10
  "stepping-group": "Stepping Group",
11
  instructor: "Instructor",
12
  class: "Class",
13
};
14
 
15
function stamp(d: Date | null | undefined) {
16
  if (!d) return "";
17
  return new Date(d)
18
    .toLocaleString("en-US", {
19
      month: "short",
20
      day: "numeric",
21
      year: "numeric",
22
    })
23
    .toUpperCase();
24
}
25
 
26
export default async function ProfilePage({
27
  params,
28
}: {
29
  params: Promise<{ slug: string; kind: string; id: string }>;
30
}) {
31
  const { slug, kind, id } = await params;
32
  const caller = serverCaller();
33
  const city = await caller.city.bySlug({ slug });
34
  if (!city) notFound();
35
 
36
  const label = KIND_LABEL[kind];
37
  if (!label) notFound();
38
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id)) {
39
    notFound();
40
  }
41
 
42
  let title = "";
43
  let typeLine = label.toUpperCase();
44
  let body: string | null = null;
45
  let emptyBody = "Nothing on record yet.";
46
  let createdAt: Date | null = null;
47
  const meta: string[] = [];
48
 
49
  if (kind === "dj") {
50
    const dj = await caller.dj.byId({ id });
51
    if (!dj) notFound();
52
    title = dj.name;
53
    body = dj.bio ?? null;
54
    emptyBody = "No bio yet. This DJ keeps the set list close.";
55
    createdAt = dj.createdAt;
56
  } else if (kind === "promoter") {
57
    const promoter = await caller.promoter.byId({ id });
58
    if (!promoter) notFound();
59
    title = promoter.name;
60
    body = promoter.bio ?? null;
61
    emptyBody = "No bio yet. This promoter lets the sets speak.";
62
    createdAt = promoter.createdAt;
63
  } else if (kind === "instructor") {
64
    const instructor = await caller.instructor.byId({ id });
65
    if (!instructor) notFound();
66
    title = instructor.name;
67
    body = instructor.bio ?? null;
68
    emptyBody = "No bio yet. Ask about lessons at the next set.";
69
    createdAt = instructor.createdAt;
70
  } else if (kind === "stepping-group") {
71
    const group = await caller.steppingGroup.byId({ id });
72
    if (!group) notFound();
73
    title = group.name;
74
    body = group.bio ?? null;
75
    emptyBody = "No bio yet. This group lets the glide do the talking.";
76
    createdAt = group.createdAt;
77
  } else {
78
    const klass = await caller.class.byId({ id });
79
    if (!klass) notFound();
80
    title = klass.title;
81
    body = klass.instructor ? `Taught by ${klass.instructor}.` : null;
82
    emptyBody = "No detail yet. The first line gets taught soon.";
83
    createdAt = klass.createdAt;
84
    if (klass.instructor) meta.push(`WITH ${klass.instructor.toUpperCase()}`);
85
    if (klass.schedule) meta.push(klass.schedule.toUpperCase());
86
    meta.push(klass.isFree ? "FREE" : "PAID");
87
  }
88
 
89
  return (
90
    <main className="mx-auto w-full max-w-3xl px-5 py-16 sm:px-8">
91
      <Link href={`/city/${slug}/floor`} className="kicker hover:text-gold">
92
        ← The Floor
93
      </Link>
94
 
95
      <p className="kicker mt-10 text-ash">
96
        {typeLine} · {city.name}
97
      </p>
98
      <h1 className="display mt-3 text-6xl sm:text-7xl">{title}</h1>
99
 
100
      {body ? (
101
        <p className="serif mt-6 max-w-xl text-xl text-bone">{body}</p>
102
      ) : (
103
        <p className="serif mt-6 max-w-xl text-xl text-ash">{emptyBody}</p>
104
      )}
105
 
106
      <section className="mt-16 border-t border-[var(--line)] pt-10">
107
        <p className="kicker text-gold">On the record</p>
108
        <p className="kicker mt-4 text-ash">
109
          {[
110
            label.toUpperCase(),
111
            (city.metroLabel ?? city.name).toUpperCase(),
112
            ...meta,
113
            createdAt ? `EST. ${stamp(createdAt)}` : null,
114
          ]
115
            .filter(Boolean)
116
            .join(" · ")}
117
        </p>
118
      </section>
119
    </main>
120
  );
121
}